using System.Web.Mvc;
using RecruitmentAgency.Models.DataTypes;

namespace RecruitmentAgency.Models.Validation
{
    /// <summary>
    /// Validates all CV related user data
    /// </summary>
    public class CvValidator : BaseValidator
    {
        private ModelStateDictionary modelState;

        /// <summary>
        /// Initialises a new RecruitmentAgency.Validation.CvValidator instance
        /// </summary>
        public CvValidator(ModelStateDictionary modelState, string selectMessage) : base(selectMessage)
        {
            this.modelState = modelState;
        }

        /// <summary>
        /// Validates that all required PersonalDetail properties are present and are in the correct format for database storage
        /// </summary>
        /// <param name="personalDetail">The PersonalDetail instance that is to be validated</param>
        /// <returns>Returns true if the PersonalDetail instance has been verified and false if not</returns>
        public bool ValidatePersonalDetails(PersonalDetail personalDetail)
        {
            if (personalDetail.IsNull) return false;
            if (IsEmpty(personalDetail.FirstName)) modelState.AddModelError("FirstName", "This field is required.");
            if (IsEmpty(personalDetail.LastName)) modelState.AddModelError("LastName", "This field is required.");
            if (IsEmpty(personalDetail.HomePhone) && IsEmpty(personalDetail.MobilePhone)) modelState.AddModelError("HomePhone", "At least one phone number is required.");
            if (IsEmpty(personalDetail.DateOfBirth)) modelState.AddModelError("DateOfBirth", "This field is required.");
            if (IsEmpty(personalDetail.AddressLine1)) modelState.AddModelError("AddressLine1", "This field is required.");
            if (IsEmpty(personalDetail.Email1) && IsEmpty(personalDetail.Email2)) modelState.AddModelError("Email1", "At least one e-mail address is required.");
            if (IsEmpty(personalDetail.Town)) modelState.AddModelError("Town", "This field is required.");
            if (IsEmpty(personalDetail.PostCode)) modelState.AddModelError("PostCode", "This field is required.");
            ValidateContactPreference(personalDetail);
            if (ValidateSelection(personalDetail.JobSectorPreference)) modelState.AddModelError("JobSectorPreference", "This field is required.");
            if (ValidateSelection(personalDetail.Title)) modelState.AddModelError("Title", "This field is required.");
            if (ValidateSelection(personalDetail.AuthorityToWork)) modelState.AddModelError("AuthorityToWork", "This field is required.");
            if (ValidateDate(personalDetail.DateOfBirth)) modelState.AddModelError("DateOfBirth", "This field requires a date, eg.5/5/55.");
            if (ValidateHomePhone(personalDetail.HomePhone)) modelState.AddModelError("HomePhone", "Please enter a valid phone number.");
            if (ValidateMobilePhone(personalDetail.MobilePhone)) modelState.AddModelError("MobilePhone", "Please enter a valid phone number.");
            if (ValidateEmail(personalDetail.Email1)) modelState.AddModelError("Email1", "Please enter a valid e-mail address.");
            if (ValidateEmail(personalDetail.Email2)) modelState.AddModelError("Email2", "Please enter a valid e-mail address.");
            if (ValidateUrl(personalDetail.WebsiteUrl)) modelState.AddModelError("WebsiteUrl", "Please enter a valid website URL.");
            return modelState.IsValid;
        }

        private void ValidateContactPreference(PersonalDetail personalDetail)
        {
            bool failure = true;
            if (ValidateSelection(personalDetail.ContactPreference)) modelState.AddModelError("ContactPreference", "This field is required.");
            else
            {
                switch (personalDetail.ContactPreference)
                {
                    case "Home phone": failure = IsEmpty(personalDetail.HomePhone); break;
                    case "Mobile phone": failure = IsEmpty(personalDetail.MobilePhone); break;
                    case "Personal e-mail": failure = IsEmpty(personalDetail.Email1); break;
                    case "Work e-mail": failure = IsEmpty(personalDetail.Email2); break;
                }
                if (failure) modelState.AddModelError("ContactPreference", "Please supply the selected field.");
            }
        }

        /// <summary>
        /// Validates that all required PersonQualification properties are present and are in the correct format for database storage
        /// </summary>
        /// <param name="personQualification">The PersonQualification instance that is to be validated</param>
        /// <returns>Returns true if the PersonQualification instance has been verified and false if not</returns>
        public bool ValidatePersonQualification(PersonQualification personQualification)
        {
            if (personQualification.IsNull) return false;
            if (IsEmpty(personQualification.QualificationName)) modelState.AddModelError("QualificationName", "This field is required.");
            if (IsEmpty(personQualification.Subject)) modelState.AddModelError("Subject", "This field is required.");
            if (IsEmpty(personQualification.AwardedBy)) modelState.AddModelError("AwardedBy", "This field is required.");
            if (IsEmpty(personQualification.Year)) modelState.AddModelError("Year", "This field is required.");
            if (ValidateSelection(personQualification.Type)) modelState.AddModelError("Type", "This field is required.");
            if (ValidateSelection(personQualification.Result)) modelState.AddModelError("Result", "This field is required.");
            if (ValidateYear(personQualification.Year)) modelState.AddModelError("Year", "This field requires a valid year.");
            return modelState.IsValid;
        }

        /// <summary>
        /// Validates that all required PersonEmployment properties are present and are in the correct format for database storage
        /// </summary>
        /// <param name="personEmployment">The PersonEmployment instance that is to be validated</param>
        /// <returns>Returns true if the PersonEmployment instance has been verified and false if not</returns>
        public bool ValidatePersonEmployment(PersonEmployment personEmployment)
        {
            if (personEmployment.IsNull) return false;
            if (IsEmpty(personEmployment.CompanyName)) modelState.AddModelError("CompanyName", "This field is required.");
            if (IsEmpty(personEmployment.JobTitle)) modelState.AddModelError("JobTitle", "This field is required.");
            if (IsEmpty(personEmployment.StartDate)) modelState.AddModelError("StartDate", "This field is required.");
            if (IsEmpty(personEmployment.EndDate)) modelState.AddModelError("EndDate", "This field is required.");
            if (IsEmpty(personEmployment.KeyDuties)) modelState.AddModelError("KeyDuties", "This field is required.");
            if (ValidateSelection(personEmployment.IndustrySector)) modelState.AddModelError("IndustrySector", "This field is required.");
            if (ValidateDate(personEmployment.StartDate)) modelState.AddModelError("StartDate", "This field requires a date, eg.5/5/55.");
            if (ValidateDate(personEmployment.EndDate)) modelState.AddModelError("EndDate", "This field requires a date, eg.5/5/55.");
            if (ValidateDates(personEmployment.StartDate, personEmployment.EndDate))
            {
                modelState.AddModelError("StartDate", "This date must come before End date.");
                modelState.AddModelError("EndDate", "This date must come after Start date.");
            }
            return modelState.IsValid;
        }

        /// <summary>
        /// Validates that all required PersonSkill properties are present and are in the correct format for database storage
        /// </summary>
        /// <param name="personSkill">The PersonSkill instance that is to be validated</param>
        /// <returns>Returns true if the PersonSkill instance has been verified and false if not</returns>
        public bool ValidatePersonSkill(PersonSkill personSkill)
        {
            if (personSkill.IsNull) return false;
            if (IsEmpty(personSkill.SkillName)) modelState.AddModelError("SkillName", "This field is required.");
            if (IsEmpty(personSkill.YearsOfExperience)) modelState.AddModelError("YearsOfExperience", "This field is required.");
            if (ValidateSelection(personSkill.ProficiencyLevel)) modelState.AddModelError("ProficiencyLevel", "This field is required.");
            if (ValidateInteger(personSkill.YearsOfExperience)) modelState.AddModelError("YearsOfExperience", "This field requires a number.");
            else if (int.Parse(personSkill.YearsOfExperience) < 0 || int.Parse(personSkill.YearsOfExperience) > 99) modelState.AddModelError("YearsOfExperience", "That number is invalid.");
            return modelState.IsValid;
        }

        /// <summary>
        /// Validates that all required PersonReferee properties are present and are in the correct format for database storage
        /// </summary>
        /// <param name="personReferee">The PersonReferee instance that is to be validated</param>
        /// <returns>Returns true if the PersonReferee instance has been verified and false if not</returns>
        public bool ValidatePersonReferee(PersonReferee personReferee)
        {
            if (personReferee.IsNull) return false;
            if (IsEmpty(personReferee.RefereeFirstName)) modelState.AddModelError("RefereeFirstName", "This field is required.");
            if (IsEmpty(personReferee.RefereeLastName)) modelState.AddModelError("RefereeLastName", "This field is required.");
            if (IsEmpty(personReferee.Occupation)) modelState.AddModelError("Occupation", "This field is required.");
            if (IsEmpty(personReferee.YearsKnown)) modelState.AddModelError("YearsKnown", "This field is required.");
            if (IsEmpty(personReferee.RefereePhone)) modelState.AddModelError("RefereePhone", "This field is required.");
            if (IsEmpty(personReferee.RefereeAddressLine1)) modelState.AddModelError("RefereeAddressLine1", "This field is required.");
            if (IsEmpty(personReferee.RefereeTown)) modelState.AddModelError("RefereeTown", "This field is required.");
            if (IsEmpty(personReferee.RefereePostCode)) modelState.AddModelError("RefereePostCode", "This field is required.");
            if (IsEmpty(personReferee.Email)) modelState.AddModelError("Email", "This field is required.");
            if (!personReferee.PermissionToContact) modelState.AddModelError("PermissionToContact", "We can't accept a referee without " + (personReferee.PermissionToStoreDetails ? "this." : "these."));
            if (!personReferee.PermissionToStoreDetails) modelState.AddModelError("PermissionToStoreDetails", personReferee.PermissionToContact ? "We can't accept a referee without this." : " ");
            if (ValidateSelection(personReferee.RefereeTitle)) modelState.AddModelError("RefereeTitle", "This field is required.");
            if (ValidateSelection(personReferee.Relationship)) modelState.AddModelError("Relationship", "This field is required.");
            if (ValidateInteger(personReferee.YearsKnown)) modelState.AddModelError("YearsKnown", "This field requires a number.");
            if (ValidateHomePhone(personReferee.RefereePhone)) modelState.AddModelError("RefereePhone", "Please enter a valid phone number.");
            if (ValidateEmail(personReferee.Email)) modelState.AddModelError("Email", "Please enter a valid e-mail address.");
            return modelState.IsValid;
        }
    }
}